12.5.9 WaitGroupの利用
sync.WaitGroupを使用することで複数のゴルーチンの終了を待つことができる
複数ゴルーチンの場合、sync.WaitGroupを使用しないとクローズ後に送信されパニックになる可能性が出てくる
code:go
package main
import (
"fmt"
"sync"
)
// processAndGather
// num個のゴルーチンを並行実行する。各ゴルーチンはprocessorを呼んで処理する
func processAndGatherT, R any(in <-chan T, processor func(T) R, num int) []R { out := make(chan R, num)
var wg sync.WaitGroup
wg.Add(num) // num個のゴルーチンを並行に実行
for i := 0; i < num; i++ {
go func() { //
defer wg.Done() // 処理が終わったらwgをデクリメント
for v := range in { // チャネルin(mainのch)から読み込み
out <- processor(v) // processorの結果をoutに書き込む
}
}()
}
go func() { // モニタリング用のゴルーチン
wg.Wait() // すべてのゴルーチンが処理を終了するのを待つ
close(out) // すべてが終了したらチャネルoutをclose
}()
var result []R
for v := range out { // outに値が来たらresultの最後に追加
result = append(result, v)
}
return result
}
func main() {
ch := make(chan int)
go func() {
for i := 0; i < 20; i++ {
ch <- i
}
close(ch)
}()
results := processAndGather(ch, func(i int) int {
return i * 2
}, 3) // 3個のゴルーチンを並行実行する
fmt.Println(results)
}